﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Xml;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace _7DaysToDieTools.Class
{
    /// <summary>
    /// MOD管理相关操作类
    /// </summary>
    public static class ModsAction
    {
        /// <summary>
        /// 获取网上已有的MOD列表
        /// </summary>
        /// <returns></returns>
        public static List<string> LoadModNames()
        {
            NetConfig.GetConfig(true);
            List<string> listNames = new List<string>();
            XmlDocument xDoc = new XmlDocument();
            XmlElement xe = null;
            xDoc.Load(Sinfo.Data.BasePath + Sinfo.Net.File.Config);
            xe = xDoc.SelectSingleNode("/config/mods") as XmlElement;
            foreach (XmlElement item in xe.ChildNodes)
            {
                listNames.Add(item.GetAttribute("name"));
            }
            
            return listNames;
        }

        /// <summary>
        /// 获取指定MOD保存在网上的压缩文件名
        /// </summary>
        /// <param name="ModName">MOD名称</param>
        /// <returns></returns>
        public static string GetModFileName(string ModName)
        {
            NetConfig.GetConfig(true);
            XmlDocument xDoc = new XmlDocument();
            XmlElement xe = null;
            xDoc.Load(Sinfo.Data.BasePath + Sinfo.Net.File.Config);
            xe = xDoc.SelectSingleNode("/config/mods/mod[@name='" + ModName + "']") as XmlElement;
            if (xe == null)
            {
                throw new Exception("在Modx.xml中找不到名字为[" + ModName + "]的MOD");
            }
            
            return xe.InnerText;
        }

        /// <summary>
        /// 获取指定MOD的说明信息
        /// </summary>
        /// <param name="ModName">MOD名称</param>
        /// <returns></returns>
        public static string GetModInfo(string ModName)
        {
            try
            {
                if (!Directory.Exists(Sinfo.Data.Mod)) Directory.CreateDirectory(Sinfo.Data.Mod);
                string infoFile = Path.GetFileNameWithoutExtension(GetModFileName(ModName)) + ".md";
                NetAction NA = new NetAction();
                NA.DownFile(Sinfo.Net.Mod + infoFile, Sinfo.Data.Mod + infoFile);
                while (!NA.Comp)
                {
                    Thread.Sleep(100);
                    Application.DoEvents();
                }
                return File.OpenText(Sinfo.Data.Mod + infoFile).ReadToEnd();
            }
            catch(Exception x)
            {
                return "读取MOD信息出错：\n" + x.Message;
            }
        }

        /// <summary>
        /// 下载指定名称的MOD文件，并解压
        /// </summary>
        /// <param name="ModName">MOD名称</param>
        /// <param name="rtbox">信息显示框</param>
        public static void DownMod(string ModName, RichTextBox rtbox)
        {
            //MOD压缩文件名
            string netModName = GetModFileName(ModName);
            if (!Directory.Exists(Sinfo.Data.BasePath)) Directory.CreateDirectory(Sinfo.Data.BasePath);
            if (!Directory.Exists(Sinfo.Data.Mod)) Directory.CreateDirectory(Sinfo.Data.Mod);
            string LocalModName = Sinfo.Data.Mod + netModName;
            try
            {
                rtbox.AppendText("正在下载MOD...(在下载完成请新不要操作此软件！如果超过5分钟没反映，请强制关闭本软件！)\n");
                //下载MOD
                NetAction NA = new NetAction();
                NA.DownFile(Sinfo.Net.Mod + netModName, LocalModName);
                while (!NA.Comp)
                {
                    rtbox.AppendText(".");
                    Thread.Sleep(100);
                    Application.DoEvents();
                }
                rtbox.AppendText("\n下载MOD完成！\n");
            }
            catch(Exception x)
            {
                throw new Exception("下载MOD出错：\n" + x.Message, x);
            }

            try
            {
                //解压MOD
                rtbox.AppendText("正在解压MOD...\n");
                using (FileStream fs = File.Open(LocalModName, FileMode.Open))
                {
                    if (Directory.Exists(Sinfo.Data.Mod + Path.GetFileNameWithoutExtension(netModName)))
                    {
                        Directory.Delete(Sinfo.Data.Mod + Path.GetFileNameWithoutExtension(netModName), true);
                    }
                    ZipAction.UnzipDatas(fs, Sinfo.Data.Mod);
                }
                rtbox.AppendText("解压MOD完成！\n");
            }
            catch(Exception x)
            {
                throw new Exception("解压MOD出错：\n" + x.Message, x);
            }
        }

        /// <summary>
        /// 解压一个本地存在的MOD
        /// </summary>
        /// <param name="ModName">MOD名称</param>
        /// <param name="rtbox">信息显示框</param>
        public static void DecMod(string ModName,RichTextBox rtbox)
        {
            string netModName = GetModFileName(ModName);
            string LocalModName = Sinfo.Data.Mod + netModName;
            try
            {
                //解压MOD
                rtbox.AppendText("正在解压MOD...\n");
                using (FileStream fs = File.Open(LocalModName, FileMode.Open))
                {
                    ZipAction.UnzipDatas(fs, Sinfo.Data.Mod);
                }
                rtbox.AppendText("解压MOD完成！\n");
            }
            catch (Exception x)
            {
                throw new Exception("解压MOD出错：\n" + x.Message, x);
            }
        }

        /// <summary>
        /// 切换MOD
        /// </summary>
        /// <param name="ModName">MOD名称</param>
        /// <param name="rtbox">信息显示框</param>
        public static void SwitchMod(string ModName,RichTextBox rtbox)
        {
            string modPath = Sinfo.Data.Mod + Path.GetFileNameWithoutExtension(GetModFileName(ModName));
            if (!Directory.Exists(modPath)) throw new Exception("找不到下载的MOD的本地存放路径！");
            //----------------------
            rtbox.AppendText("正在切换MOD...\n");
            try
            {
                DirectoryInfo di = new DirectoryInfo(modPath);
                //1、复制文件
                foreach (FileInfo item in di.GetFiles("*", SearchOption.AllDirectories))
                {
                    string tmpDir = item.DirectoryName.Replace(modPath, Sinfo.PathCurr);
                    if (!Directory.Exists(tmpDir))
                    {
                        Directory.CreateDirectory(tmpDir);
                    }
                    item.CopyTo(tmpDir + "\\" + item.Name, true);
                }
            }
            catch(Exception x)
            {
                rtbox.AppendText("切换MOD出错：\n" + x.Message);
            }

            rtbox.AppendText("切换成功!\n");
        }

        /// <summary>
        /// 去除MOD，切换到原版
        /// </summary>
        /// <param name="rtbox">信息显示框</param>
        public static void SwitchModDefault(RichTextBox rtbox)
        {
            string modName = "七日杀A15(B105)原版";
            //本地不存在原版MOD时从网上下载
            if (!HaveLocalMod(modName))
            {
                DownMod(modName, rtbox);
            }
            else
            {
                DecMod(modName, rtbox);
            }
            //切换MOD
            string modPath = Sinfo.Data.Mod + Path.GetFileNameWithoutExtension(GetModFileName(modName));
            if (!Directory.Exists(modPath)) throw new Exception("找不到下载的MOD的本地存放路径！");
            //----------------------
            rtbox.AppendText("正在还原游戏原始无MOD状态...\n");
            try
            {
                DirectoryInfo di = new DirectoryInfo(modPath);
                //1、删除所有config
                foreach (string item in Directory.GetFiles(Sinfo.Path.Config, "*", SearchOption.AllDirectories))
                {
                    File.Delete(item);
                }
                //2、删除所有建筑
                foreach (string item in Directory.GetFiles(Sinfo.Path.Prefabs, "*", SearchOption.AllDirectories))
                {
                    File.Delete(item);
                }
                //3、复制文件
                foreach (FileInfo item in di.GetFiles("*", SearchOption.AllDirectories))
                {
                    string tmpDir = item.DirectoryName.Replace(modPath, Sinfo.PathCurr);
                    if (!Directory.Exists(tmpDir))
                    {
                        Directory.CreateDirectory(tmpDir);
                    }
                    item.CopyTo(tmpDir + "\\" + item.Name, true);
                }
                //4、删除以‘-’开头的目录
                foreach (DirectoryInfo item in di.GetDirectories("-*"))
                {
                    if (Directory.Exists(Sinfo.PathCurr + item.Name))
                    {
                        Directory.Delete(Sinfo.PathCurr + item.Name);
                    }
                    if (Directory.Exists(Sinfo.PathCurr + item.Name.Remove(0, 1)))
                    {
                        Directory.Delete(Sinfo.PathCurr + item.Name.Remove(0, 1), true);
                    }
                }
            }
            catch(Exception x)
            {
                rtbox.AppendText("还原环境出错：\n" + x.Message);
            }
            rtbox.AppendText("还原到原始MOD成功!\n");
        }

        /// <summary>
        /// 检测本地是否存在指定MOD的压缩文件包
        /// </summary>
        /// <param name="ModName">MOD名称</param>
        /// <returns></returns>
        public static bool HaveLocalMod(string ModName)
        {
            try
            {
                if (File.Exists(Sinfo.Data.Mod + GetModFileName(ModName)))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

    }
}
